package apps.business.process.sales.bank.deduction.requested;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import jpa.entitys.promis.common.CostProject;
import org.apache.log4j.Logger;
import promis.utility.CommonService;
import apps.promis.in.common.ProjectAction;
import apps.promis.out.sales.VwSyncMktBankDeduRequAction;

public class SalesBankDeductionThreadPoolTest{
	
	private static final Logger log = Logger.getLogger(SalesBankDeductionThreadPoolTest.class);

	public static void main(String[] args) throws Exception {
	
	List<CostProject> lst1 = new ProjectAction().findAll();
	log.info("CostProject Size:"+ CommonService.getSize(lst1));
	
	System.out.println("CostProject Size:"+ CommonService.getSize(lst1));
	System.out.print("Please any key : "); System.in.read();
	
	List<String> docType_list = new ArrayList<String>();
	docType_list.add("BS");
	docType_list.add("CS");
	docType_list.add("CH");
	
	
	for(String docType : docType_list)
	{
		for(CostProject project : lst1){
			int totalRow = -1;
	    	List<Object[]> lst = null;
	    	try{
	    		lst = new VwSyncMktBankDeduRequAction().findGroupAll(project.getId().getCompany(), project.getId().getProject(), null, null);				
	    		totalRow = CommonService.getSize(lst);  	
		    	log.info("totalRow = " + totalRow);
	    		
	    	}catch(Exception e)
	    	{
	    		log.error(e.getMessage());
				System.err.println(e.getMessage());
	    	}
	    	
	    	/////////////////////////////////////////////////////////////////////////
		    int numTasks = totalRow;	    
		    int numThreads = 1;		    
		    log.info("numTasks=" + numTasks + " || numThreads=" + numThreads);

		    // create the thread pool
		    ThreadPool threadPool = new ThreadPool(numThreads);

		    // run example tasks
		    for (int i = 0; i < numTasks; i++) {
		    	
		    	Object[] value = lst.get(i);
				String contractNo = CommonService.IsNullRNull(value[2]);
				String syncIsstaging = CommonService.IsNullRNull(value[3]);
				String status = CommonService.IsNullRNull(value[4]);				
				String issync = "N";
				
				threadPool.runTask(createTask(project.getId().getCompany(), project.getId().getProject(), contractNo, status, syncIsstaging, issync, i) );   
			}
		    
		    // close the pool and wait for all tasks to finish.
			   threadPool.join();
		  }	
	}
}

	private static Runnable createTask(final String company, final String project, final String contractNo, final String status, final String syncIsstaging, final String issync, final int taskID) {
    return new Runnable() {
      public void run() {
        System.out.println("Task " + taskID + " || customer "+ company+ " ||  project "+ project+ " || contractNo "+ contractNo+ " || status "+ status+ " || syncIsstaging "+ syncIsstaging+ " || issync "+ issync+ " : start" + (new Date()));
        try {
			
        	new MktBankDeduRequProcessing().Processing(company, project, contractNo, status, syncIsstaging);
			
		} catch (Exception e) {
			log.error(e.getMessage());
			System.err.println(e.getMessage());
		}
        
        try {
          Thread.sleep(500);
        } catch (InterruptedException ex) {
        	log.error(ex.getMessage());
			System.err.println(ex.getMessage());
        }
        System.out.println("Task " + taskID + " || customer "+ company+ " || project "+ project+ " || contractNo "+ contractNo+ " || status "+ status+ " || syncIsstaging "+ syncIsstaging+ " || issync "+ issync+ " : end");
      }
    };
  }
}
/**
 * A thread pool is a group of a limited number of threads that are used to
 * execute tasks.
 */

class ThreadPool extends ThreadGroup {

  private boolean isAlive;
  private LinkedList taskQueue;
  private int threadID;
  private static int threadPoolID;

  /**
   * Creates a new ThreadPool.
   * 
   * @param numThreads
   *            The number of threads in the pool.
   */
  public ThreadPool(int numThreads) {
    super("ThreadPool-" + (threadPoolID++));
    setDaemon(true);

    isAlive = true;

    taskQueue = new LinkedList();
    for (int i = 0; i < numThreads; i++) {
      new PooledThread().start();
    }
  }

  /**
   * Requests a new task to run. This method returns immediately, and the task
   * executes on the next available idle thread in this ThreadPool.
   * <p>
   * Tasks start execution in the order they are received.
   * 
   * @param task
   *            The task to run. If null, no action is taken.
   * @throws IllegalStateException
   *             if this ThreadPool is already closed.
   */
  public synchronized void runTask(Runnable task) {
    if (!isAlive) {
      throw new IllegalStateException();
    }
    if (task != null) {
      taskQueue.add(task);
      notify();
    }

  }

  protected synchronized Runnable getTask() throws InterruptedException {
    while (taskQueue.size() == 0) {
      if (!isAlive) {
        return null;
      }
      wait();
    }
    return (Runnable) taskQueue.removeFirst();
  }

  /**
   * Closes this ThreadPool and returns immediately. All threads are stopped,
   * and any waiting tasks are not executed. Once a ThreadPool is closed, no
   * more tasks can be run on this ThreadPool.
   */
  public synchronized void close() {
    if (isAlive) {
      isAlive = false;
      taskQueue.clear();
      interrupt();
    }
  }

  /**
   * Closes this ThreadPool and waits for all running threads to finish. Any
   * waiting tasks are executed.
   */
  public void join() {
    // notify all waiting threads that this ThreadPool is no
    // longer alive
    synchronized (this) {
      isAlive = false;
      notifyAll();
    }

    // wait for all threads to finish
    Thread[] threads = new Thread[activeCount()];
    int count = enumerate(threads);
    for (int i = 0; i < count; i++) {
      try {
        threads[i].join();
      } catch (InterruptedException ex) {
      }
    }
  }

  /**
   * A PooledThread is a Thread in a ThreadPool group, designed to run tasks
   * (Runnables).
   */
  private class PooledThread extends Thread {

    public PooledThread() {
      super(ThreadPool.this, "PooledThread-" + (threadID++));
    }

    public void run() {
      while (!isInterrupted()) {

        // get a task to run
        Runnable task = null;
        try {
          task = getTask();
        } catch (InterruptedException ex) {
        }

        // if getTask() returned null or was interrupted,
        // close this thread by returning.
        if (task == null) {
          return;
        }

        // run the task, and eat any exceptions it throws
        try {
          task.run();
        } catch (Throwable t) {
          uncaughtException(this, t);
        }
      }
    }
  }
}